<template>
    <div ref="editorRef" id="container" class="editor" :style="{
        height:props.height ? props.height : `calc(100vh - 118px)`
    }"></div>
</template>

<script setup lang="ts">
import { nextTick, onMounted, ref, useTemplateRef, watch } from 'vue';
import { useTargetData } from '@/views/dataview/pages/design/components/contentConfiguration/hooks/useTargetData';
import { basicSetup } from "codemirror"
import { javascript } from "@codemirror/lang-javascript"
import { json } from '@codemirror/lang-json'
import {xml} from '@codemirror/lang-xml'
import CodeMirror from 'vue-codemirror6';
import { Compartment, EditorState, StateEffect, type Extension } from "@codemirror/state"
import { oneDark } from '@codemirror/theme-one-dark'
import { defaultKeymap } from '@codemirror/commands'
import { keymap, EditorView } from '@codemirror/view';
import { showMsg } from '@/utils';
// @ts-ignore
import jsonlint from 'jsonlint-mod'
import { linter, lintGutter } from '@codemirror/lint'
import contextMenu from '@/components/context-menu/index.vue'
import type { ContextMenuItem } from '../context-menu/types';

const { targetData } = useTargetData()

const props = withDefaults(defineProps<{
    source: any,
    editorType?: string,
    height?:number | string
}>(), {
    editorType: 'json'
})

const emits = defineEmits<{
    (e:"update",val:any):void
}>()

const editorView = ref()
const editorRef = useTemplateRef('editorRef')

const compartment = new Compartment()
const theme = EditorView.theme({
    // 编辑器主体样式
    '&': {
        backgroundColor: '#f8f9fa',
        color: '#2c3e50',
        fontSize: '14px',
        lineHeight: '1.6'
    },
    // 行号样式
    '.cm-gutters': {
        backgroundColor: '#f8f9fa',
        color: '#9ca3af',
        border: 'none'
    },
    // 当前行高亮
    '.cm-activeLine': {
        backgroundColor: '#f1f5f9'
    },
    // 选中文本背景
    '&.cm-focused .cm-selectionBackground': {
        backgroundColor: 'red'
    },
    '&.cm-focused .cm-selectionBackground.cm-selectionBackground.cm-selectionBackground': {
        backgroundColor: '#e2e8f0' // 多行选中背景
    },
    '&.cm-focused': {
        outline: 'none'
    },
    // 光标样式
    '.cm-cursor': {
        borderLeftColor: '#475569'
    },
    // JSON 语法高亮
    '.cm-string': { color: '#0f766e' },  // 字符串
    '.cm-number': { color: '#0369a1' },   // 数字
    '.cm-property': { color: '#334155' }, // 属性名
    '.cm-null': { color: '#7c3aed' },     // null
    '.cm-boolean': { color: '#7c3aed' }   // 布尔值
})

const formateJson = () => {
    console.log("格式化");
    return true
}

// 格式化快捷键
const keyMaps = keymap.of([
    {
        key: "Alt-Shift-f",
        run: formateJson
    }
])


const jsonLinter = linter((view) => {
    const doc = view.state.doc
    const diagnostics: any[] = []
    try {
        JSON.parse(doc.toString()) //能解析代表语法正常
    } catch (e: any) {
        // 获取错误位置
        const line = doc.lineAt(view.state.selection.main.head)
        diagnostics.push({
            from: line.from,
            to: line.to,
            severity: 'error',
            message: "请检查语法"
        })
    }
    return diagnostics
})

const extensions = [
    theme,
    basicSetup,
    keymap.of(defaultKeymap),
    // EditorView.updateListener.of((e)=>{
    //     const val = e.state.doc.toString()
    //     console.log(val);
    //     updateValue(val)
    // }),
    EditorView.domEventHandlers({
        blur:(event,view)=>{
            const val = editorView.value.state.doc.toString()
            updateValue(val)
        }
    })
]



const formateVal = (val:any)=>{
    if(props.editorType == 'json'){
        return typeof val ==='string' ? val : JSON.stringify(val,null,2)
    }else if(props.editorType == 'js'){
        return val
    }else if (props.editorType == 'xml'){
        return val
    }
}

const destory = ()=>{
    if (typeof editorView.value != 'undefined') {
        editorView.value.destroy()
    }
}

// 显示的时候格式化，返回数据的时候JSON化
const initEditor = () => {
    destory()
    let docVal = formateVal(props.source)
    if(props.editorType == 'json'){
        extensions.push(...[json(),lintGutter(),jsonLinter,keyMaps])
    }else if(props.editorType == 'js'){
        extensions.push(...[javascript()])
    }else if (props.editorType == 'xml'){
        extensions.push(...[xml()])
        /* 
        <?xml version="1.0" encoding="UTF-8"?>
        <root>
            <id>p2XwWxgFYp9D9_6vPcalC</id>
        </root>
        */
    }
    
    const editorState = EditorState.create({
        doc: docVal,
        extensions:extensions
    })
    
    if (editorRef.value) {
        editorView.value = new EditorView({
            state: editorState,
            parent: editorRef.value,
        })
    }
}

const updateValue = (val:any) => {
    emits('update',val)
    // if (value && editorView.value) {
    //     editorView.value.dispatch({ changes: { from: 0, to: editorView.value.state.doc.length, insert: value } })
    // }
}

const getEditorValue = () => {
    if (editorView.value) {
        try {
            return JSON.parse(editorView.value.state.doc.toString().join(''))
        } catch (e: any) {
            showMsg("JSON语法错误，请检查", 'warning')
            return null
        }
    }
}

defineExpose({
    getEditorValue,
    destory
})

onMounted(() => {
    initEditor()
})
</script>

<style lang='scss' scoped>
.editor {
    margin: 10px 0;
    overflow-y: auto;
    scrollbar-gutter: stable;
    overflow-x: hidden;

    &::-webkit-scrollbar {
        width: 6px;
        background: transparent;
        opacity: 0;
        transition: opacity 0.3s;
    }

    &:hover::-webkit-scrollbar {
        opacity: 1;
    }

    &::-webkit-scrollbar-corner,
    &::-webkit-scrollbar-thumb,
    &::-webkit-scrollbar-track {
        border-radius: 4px;
    }

    &::-webkit-scrollbar-corner,
    &::-webkit-scrollbar-track {
        background-color: transparent;
    }

    &::-webkit-scrollbar-thumb {
        background-color: transparent;
    }

    &:hover::-webkit-scrollbar-thumb {
        background-color: #a19e9e;

        &:hover {
            background-color: #ccc;
        }
    }
}
</style>